package com.code.coinprice.handlers;

import com.code.coinprice.exceptions.BizException;
import com.code.coinprice.exceptions.NoAuthorityException;
import com.code.coinprice.utils.ResponseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.util.List;

/**
 * 全局异常处理
 */
@ControllerAdvice
@Order
public class GlobalExceptionHandler {

    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 数据校验异常处理
     *
     * @param e 数据校验异常
     * @return ResponseEntity
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public Object validationErrorHandler(BindException e) {
        log.debug("参数校验异常=>", e);
        return ResponseUtil.fail(ResponseUtil.BUSINESS_ERR_NO, paramValidation(e.getAllErrors()));
    }

    /**
     * 参数异常，比如少传参数
     *
     * @param e 参数校验异常
     * @return ResponseEntity
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Object validExceptionHandler(MethodArgumentNotValidException e) {
        log.debug("参数异常=>", e);
        return ResponseUtil.fail(ResponseUtil.BUSINESS_ERR_NO, paramValidation(e.getBindingResult().getAllErrors()));
    }

    /**
     * 参数校验公共处理方法
     *
     * @param allErrors 错误集合
     * @return 错误信息
     */
    private String paramValidation(List<ObjectError> allErrors) {
        StringBuilder sb = new StringBuilder();
        if (!CollectionUtils.isEmpty(allErrors)) {
            for (ObjectError objectError : allErrors) {
                sb.append(objectError.getDefaultMessage()).append(",");
            }
        }
        String split = ",";
        if (sb.lastIndexOf(split) >= 0) {
            return sb.substring(0, sb.length() - 1);
        }
        return sb.toString();
    }

    /**
     * 自定义异常
     *
     * @param e 自定义异常
     * @return Object
     */
    @ExceptionHandler(BizException.class)
    @ResponseBody
    public Object bizExceptionErrorHandler(BizException e) {
        log.debug("自定义异常=>", e);
        return ResponseUtil.badValue(e.getErrno(), e.getMessage());
    }

    @ExceptionHandler(NoAuthorityException.class)
    @ResponseBody
    public Object noAuthorityErrorHandler(NoAuthorityException e) {
        log.debug("无权限异常=>", e);
        return ResponseUtil.noAuthority(e.getMessage());
    }

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public Object badArgumentHandler(IllegalArgumentException e) {
        log.error(e.getMessage(), e);
        return ResponseUtil.badArgumentValue();
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    @ResponseBody
    public Object badArgumentHandler(MethodArgumentTypeMismatchException e) {
        log.error(e.getMessage(), e);
        return ResponseUtil.badArgumentValue();
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    public Object badArgumentHandler(MissingServletRequestParameterException e) {
        log.error(e.getMessage(), e);
        return ResponseUtil.badArgumentValue();
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    public Object badArgumentHandler(HttpMessageNotReadableException e) {
        log.error(e.getMessage(), e);
        return ResponseUtil.badArgumentValue();
    }

    // @ExceptionHandler(ValidationException.class)
    // @ResponseBody
    // public Object badArgumentHandler(ValidationException e) {
    //     log.error(e.getMessage(), e);
    //     if (e instanceof ConstraintViolationException) {
    //         ConstraintViolationException exs = (ConstraintViolationException) e;
    //         Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
    //         for (ConstraintViolation<?> item : violations) {
    //             String message = ((PathImpl) item.getPropertyPath()).getLeafNode().getName() + item.getMessage();
    //             return ResponseUtil.fail(402, message);
    //         }
    //     }
    //     return ResponseUtil.badArgumentValue();
    // }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Object seriousHandler(Exception e) {
        log.error(e.getMessage(), e);
        return ResponseUtil.serious();
    }

}
